/*******************************************************************************
 * Copyright (c) 2006 Ultimate Technology, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Bojan Vukojevic - initial API and implementation
 *******************************************************************************/
package com.ultimatetech.cim.views;

import java.util.Enumeration;
import java.util.Vector;

import javax.wbem.cim.CIMException;
import javax.wbem.cim.CIMInstance;
import javax.wbem.cim.CIMProperty;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import com.ultimatetech.cim.CIMPlugin;
import com.ultimatetech.cim.views.CIMExplorerView.TreeClass;
import com.ultimatetech.cim.views.content.CIMQuery;


public class CIMQueryView extends ViewPart {
	private static String COLUMN_NAMES[] = new String[] {
		"Class Name", "Keys"
	};
	private TableViewer viewer;
	private Action submitQuery;	
	private Action doubleClickAction;
	private Label qLabel = null;
	private Text qText = null;	
	private Vector queryResult = null;
	Composite mainComposite = null;
	Composite tableComp = null;
	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
	 */
	public void createPartControl(Composite parent) {
		mainComposite = new Composite(parent, SWT.BORDER);
		GridLayout gl = new GridLayout();
		gl.numColumns = 1;
		gl.marginLeft = 0;
		gl.marginRight = 0;
		gl.marginTop = 0;
		gl.marginBottom = 0;
		gl.makeColumnsEqualWidth = true;
		gl.verticalSpacing = 0;
		gl.horizontalSpacing = 0;
		mainComposite.setLayout(gl);
		GridData gld = new GridData();
		gld.grabExcessHorizontalSpace = true;
		gld.grabExcessVerticalSpace = true;
		//gld.exclude = true;
		gld.verticalAlignment = SWT.FILL;
		gld.horizontalAlignment = SWT.FILL;
		mainComposite.setLayoutData(gld);
		
		createQueryEntry(mainComposite);		
		createTable(mainComposite);
		
		makeActions();
		//hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();
		//propChangeListener = new CIMPropChangeListener();
		//CIMPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(propChangeListener);

	}

	/**
	 * 
	 */
	private void createQueryEntry(Composite parent) {
		qLabel = new Label(parent, SWT.NONE | SWT.WRAP);		
		qLabel.setText("Enter query:");
		GridData lgd = new GridData();
		lgd.grabExcessHorizontalSpace = true;
		lgd.grabExcessVerticalSpace = false;
		lgd.horizontalAlignment = SWT.LEFT;
		qLabel.setLayoutData(lgd);
		
		qText = new Text(parent, SWT.BORDER | SWT.MULTI |SWT.V_SCROLL |SWT.H_SCROLL);
		GridData tgd = new GridData();
		tgd.grabExcessHorizontalSpace = true;
		tgd.grabExcessVerticalSpace = false;
		tgd.horizontalAlignment = SWT.LEFT;
		tgd.minimumHeight = 100;
		tgd.minimumWidth = 400;
		qText.setLayoutData(tgd);
		qText.setText("\n");
	}
	
	/**
	 * @param parent
	 */
	private void createTable(Composite parent) {
		tableComp = new Composite(parent, SWT.BORDER |SWT.FILL);
		FillLayout fl = new FillLayout();		
		tableComp.setLayout(fl);
		GridData gld = new GridData();
		gld.grabExcessHorizontalSpace = true;
		gld.grabExcessVerticalSpace = true;
		gld.horizontalAlignment = SWT.FILL;
		gld.verticalAlignment = SWT.FILL;	
		tableComp.setLayoutData(gld);
		viewer = new TableViewer(tableComp, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setSorter(new NameSorter());
		viewer.setInput(getViewSite());		
		addTableColumns(viewer.getTable());
		viewer.getTable().setHeaderVisible(true);		
		viewer.setColumnProperties(COLUMN_NAMES);
	}
	private void addTableColumns(Table instanceTable){
		TableColumn column = new TableColumn(instanceTable, SWT.LEFT, 0);		
		column.setText(COLUMN_NAMES[0]);
		column.setWidth(120);
		column = new TableColumn(instanceTable, SWT.LEFT, 1);
		column.setText(COLUMN_NAMES[1]);
		column.setWidth(400);		
		instanceTable.setLinesVisible(true);	
	}
	private void hookDoubleClickAction() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
	 */
	public void setFocus() {
		// TODO Auto-generated method stub

	}

	
	private void makeActions() {
		submitQuery = new Action() {
			public void run() {						
				CIMInstance ci = doQuery();									
				viewer.getTable().removeAll();
				viewer.getTable().setHeaderVisible(true);
				viewer.refresh();			
				//copLabel.setText(ci.getObjectPath().getObjectName());
				Point sz = tableComp.getSize();
				Point qts = qText.getSize();
				//mainComposite.layout(true, true);				
				//qText.setSize(qts);
				//tableComp.setSize(sz);
			}
			/**
			 *@return CIMInstance first instance from teh query or null
			 */
			private CIMInstance doQuery() {
				CIMInstance ci = null;
				String q = qText.getText();
				if(q != null && !q.trim().equals("")){
					CIMQuery cq = new CIMQuery(CIMPlugin.getDefault().getPluginPreferences());
					try {						
						Enumeration en = cq.execute(q);
						if(queryResult == null){
							queryResult = new Vector();
						}						
						if(en != null){		
							queryResult.clear();
							while(en.hasMoreElements()){
								queryResult.add(en.nextElement());
							}
							if(queryResult.size() > 0){
							ci = (CIMInstance)queryResult.get(0);							
							} else {
								showMessage("Query returned no values");
							}
						}
					} catch (CIMException e) {
						ErrorDialog ed = new ErrorDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
								"Query Error", "Query execution failed:" + e.getMessage(), 
								new Status(Status.ERROR, "CIMPlugin", e.getXmlCode(e.getID()), e.getMessage(), e),
								IStatus.ERROR);
						ed.open();
						queryResult = null;
					}									
				} else {
					showMessage("Enter query to execute");
				}
				return ci;
			}
		};
		submitQuery.setText("Query!");
		submitQuery.setToolTipText("Submit query");
		submitQuery.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
			getImageDescriptor(ISharedImages.IMG_OBJS_TASK_TSK));
		
		doubleClickAction = new Action() {
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection)selection).getFirstElement();
				try {
				if(obj instanceof CIMInstance) {
					//showMessage("Double-click detected on "+obj.toString());
					
						CIMInstanceView civ = (CIMInstanceView) 
							PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(
									"com.ultimatetech.cim.views.CIMInstanceView");
						civ.setCIMInstance((CIMInstance)obj);					
				} else if(obj instanceof TreeClass){
					//open CIMClassHierarchyView
					CIMClassHierarchyView view = (CIMClassHierarchyView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(
					"com.ultimatetech.cim.views.CIMClassHierarchyView");
					view.setCimObjectPath(((TreeClass)obj).getCop());
				}
				} catch (PartInitException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}					
				
			}
		};
	}
	
	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(submitQuery);
		/*manager.add(new Separator());
		manager.add(action2);*/
	}

	private void fillContextMenu(IMenuManager manager) {
		manager.add(submitQuery);
		//manager.add(action2);
		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}
	
	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(submitQuery);
		//manager.add(action2);
	}
	
	
	
	/*
	 * The content provider class is responsible for
	 * providing objects to the view. It can wrap
	 * existing objects in adapters or simply return
	 * objects as-is. These objects may be sensitive
	 * to the current input of the view, or ignore
	 * it and always show the same content 
	 * (like Task List, for example).
	 */
	 
	class ViewContentProvider implements IStructuredContentProvider {
		public void inputChanged(Viewer v, Object oldInput, Object newInput) {
		}
		public void dispose() {
		}
		public Object[] getElements(Object parent) {
			//Vector elems = new Vector();
			if(queryResult != null){
				return queryResult.toArray();
			}
			return new String[] { "Enter query and click on execute" };
		}
	}
	class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
		public String getColumnText(Object obj, int index) {
			if(obj instanceof CIMInstance) {
			CIMInstance ci = (CIMInstance) obj;
			switch(index){
			case 0: return ci.getClassName();
			case 1: {				
				Vector keys = ci.getKeys();				
				int sz = keys == null? 0 : keys.size();
				StringBuffer result = new StringBuffer("");
				for(int i = 0; i < sz; i++){
					if(i != 0)result.append(", ");
					CIMProperty cp = (CIMProperty)keys.get(i);
					result.append(cp.getName()).append("=").append(cp.getValue().toMOF());
				}
				return result.toString();
			}
			}
			}
			return null;	
		}
		public Image getColumnImage(Object obj, int index) {
			return getImage(obj);
		}
		public Image getImage(Object obj) {
			return null;
			
		}
	}
	class NameSorter extends ViewerSorter {
	}
	
	private void showMessage(String message) {
		MessageDialog.openInformation(
			viewer.getControl().getShell(),
			"CIM Instance View",
			message);
	}
	
}
